import CryptoJS from 'crypto-js'
import { ChaCha20Poly1305 } from '@stablelib/chacha20poly1305'
import IDEA from 'idea-cipher'
 
function intArrayToBase64(intArray) {
  const bytes = new Uint8Array(intArray)
  let binaryString = ''
  for (let i = 0; i < bytes.byteLength; i++) {
    binaryString += String.fromCharCode(bytes[i])
  }
  return btoa(binaryString)
}
 
function base64ToUint8Array(base64) {
  var binaryString = atob(base64)
  var bytes = new Uint8Array(binaryString.length)
  for (var i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i)
  }
  return bytes
}
 
const rc4_encode = (key, message) => {
  return CryptoJS.RC4.encrypt(message, key).toString()
}
 
const rc4_decode = (key, message) => {
  const decryptResult = CryptoJS.RC4.decrypt(message, key)
  return decryptResult.toString(CryptoJS.enc.Utf8)
}
 
const aes_encode = (key, message) => {
  return CryptoJS.AES.encrypt(message, key).toString()
}
 
const aes_decode = (key, message) => {
  const decryptResult = CryptoJS.AES.decrypt(message, key)
  return decryptResult.toString(CryptoJS.enc.Utf8)
}
 
const chacha20_encode = (key, nonce, message) => {
 
  if(!key || key.length < 32) {
    return 'error: key length must be at least 32 bytes'
  }
 
  if(nonce && nonce.length > 16 ) {
    return 'error: nonce length must not exceed 16 bytes'
  }
  const cipher = new ChaCha20Poly1305(new TextEncoder().encode(key))
  const a = cipher.seal(
    new TextEncoder().encode(nonce),
    new TextEncoder().encode(message)
  )
  console.log(a)
  return intArrayToBase64(a)
}
const chacha20_decode = (key, nonce, message) => {
 
  if(!key || key.length < 32) {
    return 'error: key length must be at least 32 bytes'
  }
 
  if(nonce && nonce.length > 16 ) {
    return 'error: nonce length must not exceed 16 bytes'
  }
  const cipher = new ChaCha20Poly1305(new TextEncoder().encode(key))
  const a = cipher.open(
    new TextEncoder().encode(nonce),
    base64ToUint8Array(message)
  )
  return new TextDecoder().decode(a)
}
 
const tripledes_encode = (key, message) => {
  return CryptoJS.TripleDES.encrypt(message, key).toString()
}
 
const tripledes_decode = (key, message) => {
  const decryptResult = CryptoJS.TripleDES.decrypt(message, key)
  return decryptResult.toString(CryptoJS.enc.Utf8)
}
 
const blowfish_encode = (key, iv, message) => {
  if(iv && iv.length > 8 ) {
    return 'error: iv length must not exceed 8 bytes'
  }
  key = CryptoJS.enc.Utf8.parse(key)
  iv = CryptoJS.enc.Utf8.parse(iv)
  var ciphertext = CryptoJS.Blowfish.encrypt(message, key, { iv: iv })
  return ciphertext.toString()
}
 
const blowfish_decode = (key, iv, message) => {
  if(iv && iv.length > 8 ) {
    return 'error: iv length must not exceed 8 bytes'
  }
  iv = CryptoJS.enc.Utf8.parse(iv)
  key = CryptoJS.enc.Utf8.parse(key)
  var decrypted = CryptoJS.Blowfish.decrypt(message, key, { iv: iv })
  return decrypted.toString(CryptoJS.enc.Utf8)
}
 
const idea_encode = (key, message) => {
  if(!key || key.length < 7) {
    return 'error: key length must be at least 7 bytes'
  }
  let ideaCipher = new IDEA(key)
  let encryptedstr = ideaCipher.encrypt(message)
  let decryptedstr = ideaCipher.decrypt(
    base64ToUint8Array(intArrayToBase64(encryptedstr))
  )
  while (decryptedstr[decryptedstr.length - 1] == 0x00) {
    decryptedstr = decryptedstr.slice(0, decryptedstr.length - 1)
  }
  return intArrayToBase64(encryptedstr)
}
 
const idea_decode = (key, message) => {
  if(!key || key.length < 7) {
    return 'error: key length must be at least 7 bytes'
  }
  const ideaCipher = new IDEA(key)
  let decryptedstr = ideaCipher.decrypt(base64ToUint8Array(message))
  while (decryptedstr[decryptedstr.length - 1] == 0x00) {
    decryptedstr = decryptedstr.slice(0, decryptedstr.length - 1)
  }
  return new TextDecoder().decode(decryptedstr)
}
 
const RC4 = {
  encode: rc4_encode,
  decode: rc4_decode
}
const AES = {
  encode: aes_encode,
  decode: aes_decode
}
const ChaCha20 = {
  encode: chacha20_encode,
  decode: chacha20_decode
}
const TripleDES = {
  encode: tripledes_encode,
  decode: tripledes_decode
}
const Blowfish = {
  encode: blowfish_encode,
  decode: blowfish_decode
}
const IDEACrypto = {
  encode: idea_encode,
  decode: idea_decode
}
 
export { RC4, AES, ChaCha20, TripleDES, Blowfish, IDEACrypto }